package com.autumn.config.util;

import com.autumn.common.api.domain.entities.IEntity;
import com.autumn.common.api.domain.entities.auditing.ISoftDelete;
import com.autumn.config.api.consts.ConfigureConsts.StatusConsts;
import com.autumn.config.api.dto.input.StatusInput;
import com.autumn.config.entities.IStatusEntity;
import com.autumn.domain.repositories.IEntityRepository;
import com.autumn.mybatis.criterion.Criteria;
import com.autumn.mybatis.criterion.LockModeEnum;
import com.autumn.util.AutoMapUtils;
import com.autumn.util.ExceptionUtils;
import com.autumn.util.data.DbAuditingUtils;
import com.autumn.util.data.DbQueryUtils;

import java.util.Map;

/**
 * 服务帮助
 * 
 * @author 老码农
 *         <p>
 *         Description
 *         </p>
 * @date 2018-01-01 00:55:51
 */
public class ServiceUtils {

	/**
	 * 是否存在 (自动过滤 ISoftDelete 接口)
	 * 
	 * @param repository
	 *            仓储
	 * @param entityClass
	 *            实体类型
	 * @param propertyMap
	 *            属性
	 * @return
	 */
	public static <TEntity extends IEntity<TPrimaryKey>, TPrimaryKey> boolean exist(
			IEntityRepository<TEntity, TPrimaryKey> repository, Class<TEntity> entityClass,
			Map<String, Object> propertyMap) {
		Criteria criteria = new Criteria(entityClass);
		for (Map.Entry<String, Object> entry : propertyMap.entrySet()) {
			criteria = criteria.eq(entry.getKey(), entry.getValue());
		}
		if (ISoftDelete.class.isAssignableFrom(entityClass)) {
			criteria = criteria.eq("isDelete", false);
		}
		criteria = criteria.lock(LockModeEnum.UPDATE);
		return repository.countByWhere(criteria.builderSection()) > 0;
	}

	/**
	 * 是否存在(自动过滤 ISoftDelete 接口)
	 * 
	 * @param repository
	 *            仓储
	 * @param entityClass
	 *            实体类型
	 * @param propertyName
	 *            属性名称
	 * @param value
	 *            属性值
	 * @return
	 */
	public static <TEntity extends IEntity<TPrimaryKey>, TPrimaryKey> boolean exist(
			IEntityRepository<TEntity, TPrimaryKey> repository, Class<TEntity> entityClass, String propertyName,
			Object value) {
		Criteria criteria = new Criteria(entityClass);
		criteria = criteria.eq(propertyName, value);
		if (ISoftDelete.class.isAssignableFrom(entityClass)) {
			criteria = criteria.eq("isDelete", false);
		}
		criteria = criteria.lock(LockModeEnum.UPDATE);
		return repository.countByWhere(criteria.builderSection()) > 0;
	}

	/**
	 * 更新状态帮助
	 * 
	 * @param repository
	 * @param entityClass
	 * @param input
	 * @return
	 */
	public static <TEntity extends IStatusEntity> TEntity updateStatus(IEntityRepository<TEntity, Long> repository,
			Class<TEntity> entityClass, StatusInput input) {
		if (input == null || input.getId() == null || input.getStatus() == null) {
			ExceptionUtils.throwValidationException("id、status 都不能为 null。");
		}
		if (input.getStatus().intValue() >= StatusConsts.STATUS_DRAFT
				&& input.getStatus().intValue() <= StatusConsts.STATUS_RELEASE) {
			String name = StatusConsts.getName(input.getStatus().intValue());
			TEntity result = DbQueryUtils.queryById(repository, entityClass, input.getId(), LockModeEnum.UPDATE);
			if (result == null) {
				ExceptionUtils.throwValidationException("指定的数据不存在，无法执行[" + name + "]操作。");
			}
			if (result.getStatus().intValue() == input.getStatus().intValue()) {
				ExceptionUtils.throwValidationException("已处于[" + name + "]状态。");
			}
			result.setStatus(input.getStatus());
			DbAuditingUtils.updateSetProperty(result);
			repository.update(result);
			return result;

		} else {
			throw ExceptionUtils.throwValidationException("状态不正确或不支持。");
		}
	}

	/**
	 * 更新状态帮助
	 * 
	 * @param repository
	 * @param entityClass
	 * @param resultClass
	 * @param input
	 * @return
	 */
	public static <TEntity extends IStatusEntity, TResult> TResult updateStatus(
			IEntityRepository<TEntity, Long> repository, Class<TEntity> entityClass, Class<TResult> resultClass,
			StatusInput input) {
		TEntity result = updateStatus(repository, entityClass, input);
		return AutoMapUtils.map(result, resultClass);
	}

}
